/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package blueprint4j.gui;

import blueprint4j.Constants;
import blueprint4j.gui.*;
import blueprint4j.utils.*;


import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class JoinPanel extends JPanel implements ActionListener {
	private Bindable source;
	private Binder binder;
	private JoinPanelJoiner joiner;
	private JoinPanelFieldBinder[] binders;
	private DefaultTableModel model;
	private JScrollPane scroll = new JScrollPane();
	private JTable table = null;
	private Vector column_names = null;
	private VectorBindable entites_list = new VectorBindable();
	private HashMap map = new HashMap();
	private HashMap box_map_index = new HashMap();
	private HashMap box_map = new HashMap();
	private HashMap box_map_destination = new HashMap();
	private Vector data = new Vector();
	private boolean single_join=false;

	public JoinPanel(Binder p_binder, Bindable p_source, JoinPanelJoiner p_joiner, JoinPanelFieldBinder[] p_binders)
	//throws SQLException, DataException {
	throws BindException	{
		super(new BorderLayout());
		binder = p_binder;
		source = p_source;
		joiner = p_joiner;
		binders = p_binders;

		build();
	}

	public void setSingleJoin(boolean single){
		single_join=single;
	}

	private void build()
	throws BindException {
		removeAll();
		// Add scroll pane
		add(scroll, BorderLayout.CENTER);
		scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

		// Create table details
		column_names = new Vector();
		column_names.add("");
		for (int t = 0;t < binders.length;t++) {
			column_names.add(binders[t].getColumnName());
		}

		setPreferredSize(new Dimension(270, 150));

		refresh();
	}

	public void refresh()
	throws BindException	{
		data = new Vector();
		entites_list.removeAll();
		box_map_index.clear();
		box_map.clear();
		box_map_destination.clear();
		ButtonGroup group=null;
		if (single_join){
			group=new ButtonGroup();
		}
		int count=0;
		for (Bindable item = joiner.getDestinations();item != null;item = item.getNextBindable(),count++) {
			entites_list.add(item);
			Vector row = new Vector();
			Bindable join = joiner.getJoin(source, item);
			JToggleButton box;
			if (single_join){
				box=new JRadioButton();
				group.add(box);
			}else{
				box = new JCheckBox();
			}

			if (join != null) {
				box.setSelected(true);
			}
			box.setOpaque(false);
			row.add(box);
			box.addActionListener(this);
			box_map.put(box, join);
			box_map_index.put(box,new Integer(count));
			box_map_destination.put(box, item);
			for (int y = 0;y < binders.length;y++) {
				row.add(binders[y].getFieldComponent(binder, item, join));
			}
			data.add(row);
		}

		model = new DefaultTableModel(data, column_names);
		table = new JTable(model);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setRowSelectionAllowed(false);
		table.setColumnSelectionAllowed(false);
		table.setCellSelectionEnabled(false);
		table.setShowVerticalLines(false);
		table.setShowHorizontalLines(false);
		table.setFocusable(false);
		table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		table.setDefaultEditor(
			Object.class,
			new TableCellEditor() {
				private Object last_value;
				public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
					last_value = value;
					if (value instanceof JLabel || !(value instanceof JComponent)) {
						return null;
					}
					JComponent component = (JComponent)value;
					return component;
				}
				public void addCellEditorListener(CellEditorListener l) {}
				public void cancelCellEditing() {}
				public Object getCellEditorValue() {
					return last_value;
				}
				public boolean isCellEditable(EventObject anEvent) {
					Object value = anEvent.getSource();
					return !(value instanceof JLabel || !(value instanceof JComponent));
				}
				public void removeCellEditorListener(CellEditorListener l) {}
				public boolean shouldSelectCell(EventObject anEvent) {
					return isCellEditable(anEvent);
				}
				public boolean stopCellEditing() {
					return true;
				}
			}
		);

		table.setIntercellSpacing(new Dimension(0, 0));
		table.setDefaultRenderer(
			Object.class,
			new TableCellRenderer() {
				public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
					JComponent component = (JComponent)value;
					if (map.get(component) != null) {
						component.setOpaque(((Boolean)map.get(component)).booleanValue());
					} else {
						map.put(component, new Boolean(component.isOpaque()));
					}
					if (!component.isOpaque()) {
						if (isSelected) {
							component.setOpaque(true);
							component.setBackground(Gui.getRowSelectedColor());
						} else {
							if (((row / 3)&1) == 1) {
								component.setOpaque(true);
								component.setBackground(Gui.getRowHighlighterColor());
							} else {
								component.setOpaque(true);
								component.setBackground(Color.WHITE);
							}
						}
					}
					return component;
				}
			}
		);
		TableColumn c = table.getColumn("");
		c.setPreferredWidth(15);
		for (int t = 0;t < binders.length;t++) {
			c = table.getColumn(binders[t].getColumnName());
			c.setPreferredWidth(binders[t].getColumnWidth());
		}
		scroll.setViewportView(table);
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getSource() instanceof JToggleButton) {
			JToggleButton box = (JToggleButton)e.getSource();
			Bindable join = (Bindable)box_map.get(box);
			if (box.isSelected()) {
				if (join == null) {
					try {
						join = joiner.createNewJoin(source, (Bindable)(box_map_destination.get(box)));
						binder.addBindable(join);
						box_map.put(box, join);
					} catch (Exception ex) {
						ex.printStackTrace();
						Log.critical.out( ex);
						System.exit( -1);
					}
				}
			} else {
				if (join != null) {
					try {
						joiner.removeJoin(binder,join);
						join=null;
					} catch (BindException be){
						be.printStackTrace();
						Log.critical.out(be);
						System.exit(-1);
					}
				}
				box_map.put(box, join);
			}
			// Rebuild row
			for (int x = 0;x < binders.length;x++) {
				model.setValueAt(
					binders[x].getFieldComponent(binder, (Bindable)box_map_destination.get(box), join),
					((Integer)box_map_index.get(box)).intValue(),
					x + 1
				);
			}
		}
	}
}

